/* shttpd - schedule tasks
   Copyright (C) 2018 Ariadne Devos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "worker.h"

#include <sHT/compiler.h>
#include <sys/epoll.h>
#include <sHT/index.h>
#include <sHT/scheduling.h>
#include <sHT/task.h>
#include <sHT/test.h>

__attribute__((returns_nonnull))
__attribute__((const))
static struct sHT_task *
sHT_task_from_epoll_data(epoll_data_t d)
{
	/* Alternatively, store an offset into worker->tasks.
	   That should speed up worker transmutation up to some degree
	   by being able to hand an epoll set over instead of having
	   to create it all over, or modifying the data value. */

	/* If the pointer is invalid, e.g. due to buggy migration code
	   (forgetting to fix up pointers), an assert would make this
	   crash. Otherwise, a segfault would do that.

	   Both work most of the time, but sometimes they don't, so
	   there is not much of an advantage. So don't check.
	   (The kernel is trusted.) */

	return d.ptr;
}

void
sHT_schedule_events(struct sHT_worker *worker, size_t n)
{
	size_t i;
	sHT_index_iterate(i, n) {
		struct epoll_event e = worker->epoll_events[i];
		struct sHT_task *task = sHT_task_from_epoll_data(e.data);
		task->epollflags |= e.events;
		/* Something can be done, if there is spare memory, even
		   if 'something' is ignoring it. Edge-triggered. */
		sHT_qadd_try(&worker->todo.queue, task);
	}
}
